package p35_HandlerMapper和HandlerAdapter其3;

import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.resource.CachingResourceResolver;
import org.springframework.web.servlet.resource.EncodedResourceResolver;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;

import java.util.List;
import java.util.Map;

/**
 * 这节介绍一对处理静态资源的处理器映射器和处理器适配器
 * springboot中，对静态资源的请求就是使用的这组映射器和适配器
 */
@Configuration
public class _1_SimpleUrlHandlerMapping和HttpRequestHandlerAdapter {

    public static void main(String[] args) {
        AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
    }

    @Bean
    public SimpleUrlHandlerMapping simpleUrlHandlerMapping(ApplicationContext context) {
        /**
         * 收集ResourceHttpRequestHandler类型的处理器，并用bean的名字和ResourceHttpRequestHandler建立映射
         */
        Map<String, ResourceHttpRequestHandler> map = context.getBeansOfType(ResourceHttpRequestHandler.class);
        SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
        simpleUrlHandlerMapping.setUrlMap(map);
        return simpleUrlHandlerMapping;
    }
    //根据SimpleUrlHandlerMapping返回的ResourceHttpRequestHandler，由于知道了类型，所以直接调用其内部的handleRequest方法
    @Bean
    public HttpRequestHandlerAdapter httpRequestHandlerAdapter() {
        return new HttpRequestHandlerAdapter();
    }

    /**
     * 下面定义了几个处理器,SimpleUrlHandlerMapping会收集所有ResourceHttpRequestHandler类型的处理器
     * 用bean的名字(通配符) ---> ResourceHttpRequestHandler对象，建立一个映射
     * 当然以上操作要手动处理
     *
     */
    @Bean("/img/**")
    public ResourceHttpRequestHandler handler1() {
        //ResourceHttpRequestHandler是处理静态的处理器(跟前面的控制器方法类型，只不过这个处理器是针对静态资源，而非动态代码的)
        ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
        //设置静态资源目录
        handler.setLocations(List.of(new ClassPathResource("p35/img/")));
        //设置资源解析器，责任链模式
        handler.setResourceResolvers(List.of(
                new CachingResourceResolver(new ConcurrentMapCache("cache")),  //读取资源时可以加入缓存
                new EncodedResourceResolver(),  //读取压缩资源
                new PathResourceResolver()  //从磁盘上直接读取资源
        ));
        return handler;
    }
    @Bean("html/**")
    public ResourceHttpRequestHandler handler2() {
        //ResourceHttpRequestHandler是处理静态的处理器(跟前面的控制器方法类型，只不过这个处理器是针对静态资源，而非动态代码的)
        ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
        //设置静态资源目录
        handler.setLocations(List.of(new ClassPathResource("p35/html/")));
        return handler;
    }

    /**
     * ResourceHttpRequestHandler内部找静态资源，是委托的资源解析器组件去获取资源流
     * 我们可以手动设置资源解析器
     */
    @Bean("zip/**")
    public ResourceHttpRequestHandler handler3() {
        ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
        handler.setLocations(List.of(new ClassPathResource("p35/zip/")));
        //设置资源解析器，责任链模式
        handler.setResourceResolvers(List.of(
                new CachingResourceResolver(new ConcurrentMapCache("cache")),  //读取资源时可以加入缓存
                new EncodedResourceResolver(),  //读取压缩资源
                new PathResourceResolver()  //从磁盘上直接读取资源
        ));
        return handler;
    }
}
